﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Microsoft Corp." file="DeploymentManagerTests.cs">
//   All rights reserved. See License.txt in the project root for license information.
// </copyright>
// 
// --------------------------------------------------------------------------------------------------------------------
namespace DeploymentManagerTests
{
    using System.Collections.Generic;
    using System.Linq;

    using CloudBlitz.DeploymentManager;
    using CloudBlitz.DeploymentManager.DeploymentWorkflow;

    using Moq;

    using TestSupport;

    using Xunit;

    public class DeploymentManagerTests
    {
        [Fact]
        public void CanParallelOperationCalculateProgressWeight()
        {
            var operation1 = new TestDeploymentOperation(5);
            var operation2 = new TestDeploymentOperation(10);

            var parallelOperation = new ParallelOperation(new List<IDeploymentOperation>
            {
                operation1,
                operation2
            });

            Assert.Equal(parallelOperation.ProgressWeight, 15);
        }

        [Fact]
        public void CanSerialOperationCalculateProgressWeight()
        {
            var operation1 = new TestDeploymentOperation(5);
            var operation2 = new TestDeploymentOperation(10);

            var parallelOperation = new SerialOperation(new List<IDeploymentOperation>
            {
                operation1,
                operation2
            });

            Assert.Equal(parallelOperation.ProgressWeight, 15);
        }

        [Fact]
        public void CanWorkflowRun()
        {
            var operation1 = new TestDeploymentOperation(5);
            var operation2 = new TestDeploymentOperation(10);
            var operation3 = new TestDeploymentOperation(15);

            var parallelOperation = new SerialOperation(new List<IDeploymentOperation>
            {
                operation1,
                operation2
            });

            var workflow = new SerialOperation(new List<IDeploymentOperation>
            {
                parallelOperation,
                operation3
            });

            var result = workflow.Execute(new Mock<DeploymentContext>().Object);
            Assert.True(result.Status == DeploymentOperationStatus.Succeeded);
        }

        [Fact]
        public void CanWorkflowFail()
        {
            var progressReports = new List<ProgressChangedEventArgs>();

            var operation1 = new TestDeploymentOperation(5);
            var operation2 = new TestDeploymentOperation(10, false);
            var operation3 = new TestDeploymentOperation(15);

            var parallelOperation = new SerialOperation(new List<IDeploymentOperation>
            {
                operation1,
                operation2
            });

            var workflow = new SerialOperation(new List<IDeploymentOperation>
            {
                parallelOperation,
                operation3
            });

            workflow.ProgressChanged += (s, a) => progressReports.Add(a);

            var result = workflow.Execute(new Mock<DeploymentContext>().Object);
            Assert.True(result.Status == DeploymentOperationStatus.Failed);
        }

        [Fact]
        public void CanWorkflowReportProgress()
        {
            var progressReports = new List<ProgressChangedEventArgs>();

            var operation1 = new TestDeploymentOperation(5);
            var operation2 = new TestDeploymentOperation(10);
            var operation3 = new TestDeploymentOperation(15);
            var operation4 = new TestDeploymentOperation(10);
            var operation5 = new TestDeploymentOperation(5);

            var serialOperation = new SerialOperation(new List<IDeploymentOperation>
            {
                operation1,
                operation2
            });

            var parallelOperation = new ParallelOperation(new List<IDeploymentOperation>
            {
                serialOperation,
                operation3,
                operation4
            });

            var workflow = new SerialOperation(new List<IDeploymentOperation>
            {
                parallelOperation,
                operation5
            });

            workflow.ProgressChanged += (s, a) => progressReports.Add(a);

            workflow.Execute(new Mock<DeploymentContext>().Object);

            Assert.NotEmpty(progressReports);

            for (int i = 1; i < progressReports.Count; i++)
            {
                Assert.True(progressReports[i - 1].Progress <= progressReports[i].Progress);

                Assert.True(progressReports[i - 1].Progress <= 100);
                Assert.False(string.IsNullOrEmpty(progressReports[i - 1].Message));
                
                Assert.True(progressReports[i].Progress <= 100);
                Assert.False(string.IsNullOrEmpty(progressReports[i].Message));
            }

            Assert.Equal(progressReports.Last().Progress, 100);
        }
    }
}